package com.bdqn.controller;

import com.alibaba.csp.sentinel.SphO;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.bdqn.base.R;
import com.bdqn.logger.WebLogger;
import com.alibaba.csp.sentinel.Entry;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * HelloController
 *
 * @author LILIBO
 * @since 2023-02-22
 */
@Api(tags = "安全认证测试接口")
@RestController
@RequestMapping("/hello")
public class HelloController {

    /**
     * 有sys权限的用户才能访问 /hi-a 接口
     *
     * @return
     */
    @ApiOperation("Hi A 认证授权测试接口")
    @WebLogger("Hi A 认证授权测试接口")
    @PreAuthorize("hasAuthority('sys')") // 拥有sys权限才能访问
    @GetMapping("/hi-a")
    public R sayHiA()  {
        return R.success("A say Hi 老王");
    }

    /**
     * 基于Sentinel使用SphU对 /hi-b 接口进行流量控制
     *
     * @return
     */
    @ApiOperation("Hi B 认证授权测试接口")
    @WebLogger("Hi B 认证授权测试接口")
    @PreAuthorize("hasAuthority('sys')") // 拥有sys权限才能访问
    @GetMapping("/hi-b")
    public R sayHiB()  {
        // 基于Sentinel使用SphU手动定义资源对接口限流
        return sentinelBySphUSayHiB();
    }

    /**
     * 基于Sentinel使用SphU手动定义资源对 /hi-b 接口进行流量控制
     *
     * @return
     */
    public R sentinelBySphUSayHiB() {
        Entry entry = null;
        try {
            // 手动定义资源
            entry = SphU.entry("sentinelBySphUSayHiB");
            // 业务逻辑处理
            return R.success("B say Hi 老王");
        } catch (BlockException e) {
            // 流量控制处理
            return R.failure("【SpringCloud】sayHiB 服务被限流了。");
        } finally {
            if (entry != null) {
                entry.exit();
            }
        }
    }

    /**
     * 基于Sentinel使用SphU对 /hi-c 接口进行流量控制
     *
     * @return
     */
    @ApiOperation("Hi C 认证授权测试接口")
    @WebLogger("Hi C 认证授权测试接口")
    @PreAuthorize("hasAuthority('sys')") // 拥有sys权限才能访问
    @GetMapping("/hi-c")
    public R sayHiC()  {
        // 基于Sentinel使用SphU手动定义资源对接口限流
        return sentinelBySphOSayHiC();
    }

    /**
     * 基于Sentinel使用SphO手动定义资源对 /hi-c 接口进行流量控制
     *
     * @return
     */
    public R sentinelBySphOSayHiC() {
        // 手动定义资源
        if (SphO.entry("sentinelBySphOSayHiC")) {
            try {
                // 业务逻辑处理
                return R.success("C say Hi 老王");
            } finally {
                SphO.exit();
            }
        } else {
            // 流量控制处理
            return R.failure("【SpringCloud】sayHiC 服务被限流了。");
        }
    }

    /**
     * 基于Sentinel使用注解方式对 /hi-d 接口进行流量控制（推荐）
     *
     * @return
     */
    @ApiOperation("Hi D 认证授权测试接口")
    @WebLogger("Hi D 认证授权测试接口")
    @PreAuthorize("hasAuthority('sys')") // 拥有sys权限才能访问
    @GetMapping("/hi-d")
    @SentinelResource(value = "sentinelResourceSayHiD", blockHandler = "blockHandlerSayHiD") // 通过注解方式进行资源定义实现异常处理
    public R sayHiD()  {
        // 正常业务处理
        return R.success("D say Hi 老王");
    }

    /**
     * 通过@SentinelResource注解指定流量控制处理方法
     *
     * @param e
     * @return
     */
    public R blockHandlerSayHiD(BlockException e) {
        // 流量控制处理
        return R.failure("【SpringCloud】sayHiD 服务被限流了。");
    }
}
